/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.ncsu.csc573.project1.util;
import edu.ncsu.csc573.project1.util.Constants.PSMethod;
import java.util.Scanner;
/**
 *
 * @author svpendse1
 */
public class PSRequest {
    private PSMethod exchangeMethod;
    private int rfcNumber;
    private String version;
    private HeaderField hostField, portField, titleField;

    public static class PSRequestBuilder {
        PSMethod exchangeMethod;
        int rfcNumber;
        String version;
        HeaderField hostField, portField, titleField;
       
        public PSRequestBuilder exchangeMethod(PSMethod method) {
            this.exchangeMethod = method;
            return this;
        }

        public PSRequestBuilder rfcNumber(int rfcNumber) {
            this.rfcNumber = rfcNumber;
            return this;
        }

        public PSRequestBuilder version(String version) {
            this.version = version;
            return this;
        }

        public PSRequestBuilder hostField(HeaderField field) {
            this.hostField = field;
            return this;
        }

        public PSRequestBuilder portField(HeaderField field) {
            this.portField = field;
            return this;
        }

        public PSRequestBuilder titleField(HeaderField field) {
            this.titleField = field;
            return this;
        }

        public PSRequest build() {
            return new PSRequest(this);
        }
    }

    public PSMethod getExchangeMethod() {
        return exchangeMethod;
    }

    public void setExchangeMethod(PSMethod exchangeMethod) {
        this.exchangeMethod = exchangeMethod;
    }

    public HeaderField getHostField() {
        return hostField;
    }

    public void setHostField(HeaderField hostField) {
        this.hostField = hostField;
    }

    public HeaderField getPortField() {
        return portField;
    }

    public void setPortField(HeaderField portField) {
        this.portField = portField;
    }

    public int getRfcNumber() {
        return rfcNumber;
    }

    public void setRfcNumber(int rfcNumber) {
        this.rfcNumber = rfcNumber;
    }

    public HeaderField getTitleField() {
        return titleField;
    }

    public void setTitleField(HeaderField titleField) {
        this.titleField = titleField;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    
    private PSRequest(PSRequestBuilder builder) {
        this.exchangeMethod = builder.exchangeMethod;
        this.rfcNumber = builder.rfcNumber;
        this.version = builder.version;
        this.hostField = builder.hostField;
        this.portField = builder.portField;
        this.titleField = builder.titleField;
    }

    public String getRequestMessage() {
        StringBuilder output = new StringBuilder();

        if (this.exchangeMethod == PSMethod.CLOSE) {
            output.append(exchangeMethod.getName());
            output.append(" ");
            output.append(version);
            output.append("\r\n");
            output.append(hostField.getFieldName());
            output.append(": ");
            output.append(hostField.getValue());
            output.append("\r\n");
            output.append("\r\n");
            
            return output.toString();
        }
        else if (this.exchangeMethod == PSMethod.LIST) {

            //Line 1
            output.append(exchangeMethod.getName());
            output.append(" ALL ");
            output.append(version);
            output.append("\r\n");

            //Line 2
            output.append(hostField.getFieldName());
            output.append(": ");
            output.append(hostField.getValue());
            output.append("\r\n");

            //Line 3
            output.append(portField.getFieldName());
            output.append(": ");
            output.append(portField.getValue());
            output.append("\r\n");
            
            //Last line
            output.append("\r\n");

            return output.toString();
        } 
        //Line 1
        output.append(exchangeMethod.getName());
        output.append(" RFC ");
        output.append(rfcNumber);
        output.append(" ");
        output.append(version);
        output.append("\r\n");
        
        //Line 2
        output.append(hostField.getFieldName());
        output.append(": ");
        output.append(hostField.getValue());
        output.append("\r\n");

        //Line 3
        output.append(portField.getFieldName());
        output.append(": ");
        output.append(portField.getValue());
        output.append("\r\n");

        //Line 4
        output.append(titleField.getFieldName());
        output.append(": ");
        output.append(titleField.getValue());
        output.append("\r\n");

        output.append("\r\n");
        return output.toString(); 
    }

    //Parse a message of type PSRequest from an input string
    public static PSRequest parseFromString(String input) {
        PSRequest output = null;
        try {
            Scanner scanner = new Scanner(input);

            String method = scanner.next();
            PSMethod exchangeMethod = PSMethod.constructMethodFromName(method);
            if (exchangeMethod == null) {

                throw new Exception("Invalid exchange method : " + method);
            } else if (exchangeMethod == PSMethod.CLOSE) { 
                String version = scanner.next();
                scanner.skip("\r\n");
                scanner.skip("Host: ");
                String hostname = scanner.next();
                scanner.skip("\r\n");
                scanner.skip("\r\n");

                output = new PSRequest.PSRequestBuilder().exchangeMethod(exchangeMethod).version(version).hostField(new HeaderField("Host", hostname)).build();

                return output;
            } else if (exchangeMethod == PSMethod.LIST) {
                scanner.skip(" ALL ");
                String version = scanner.next();
                scanner.skip("\r\n");
                scanner.skip("Host: ");
                String hostname = scanner.next();
                
                scanner.skip("\r\n");
                scanner.skip("Port: ");
                int port = scanner.nextInt();
                scanner.skip("\r\n");
                scanner.skip("\r\n");

                output = new PSRequest.PSRequestBuilder().exchangeMethod(exchangeMethod).version(version).hostField(new HeaderField("Host", hostname)).portField(new HeaderField("Port", "" + port)).build();

                return output;
            }
            scanner.skip(" RFC ");
            int rfcNumber = scanner.nextInt();
            String version = scanner.next();
            scanner.skip("\r\n");
            scanner.skip("Host: ");
            String hostname = scanner.next();

            scanner.skip("\r\n");
            scanner.skip("Port: ");
            int port = scanner.nextInt();
            scanner.skip("\r\n");
            scanner.skip("Title: ");
            String title = scanner.nextLine();
            scanner.skip("\r\n");
           
            output = new PSRequest.PSRequestBuilder().exchangeMethod(exchangeMethod).hostField(new HeaderField("Host", hostname)).portField(new HeaderField("Port", "" + port)).rfcNumber(rfcNumber).titleField(new HeaderField("Title", title)).version(version).build();
            return output;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }   

    public static void main(String[] args) {
        PSRequest request = new PSRequest.PSRequestBuilder().exchangeMethod(PSMethod.ADD).rfcNumber(1000).version("1234").hostField(new HeaderField("Host", "value")).portField(new HeaderField("Port", "5268")).titleField(new HeaderField("Title", "title has this")).build();

        System.out.println(request.getRequestMessage().length());
        PSRequest.parseFromString(request.getRequestMessage());
        System.out.println(PSRequest.parseFromString(request.getRequestMessage()).getRequestMessage().length());
    }
}
